﻿#include "LbsCellocation.h"

#include "jqnet.h"
#include <qjsondocument.h>
#include <QJsonObject>
#include <qDebug>
#include <QFileDialog>
#include <QTimer>
#include <QHBoxLayout>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QRegularExpressionMatchIterator>

#include "qtcsv/reader.h"
#include "qtcsv/writer.h"
#include "qtcsv/stringdata.h"

#include "xlsxcellrange.h"
#include "xlsxchart.h"
#include "xlsxchartsheet.h"
#include "xlsxdocument.h"
#include "xlsxrichstring.h"
#include "xlsxworkbook.h"

LbsCellocation::LbsCellocation(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    QVBoxLayout* layout = new QVBoxLayout();
    ui.centralWidget->setLayout(layout);
    {
        layout->addWidget(ui.label);
        QHBoxLayout* hboxLy = new QHBoxLayout();
        layout->addLayout(hboxLy);
        {
            hboxLy->addWidget(ui.lineEdit);
            hboxLy->addWidget(ui.pushButton);
        }
        layout->addWidget(ui.textBrowser);
        layout->addWidget(ui.pushButton_2);
    }
    

    connect(ui.pushButton, &QPushButton::clicked, this, &LbsCellocation::sltSelectFile);
    connect(ui.pushButton_2, &QPushButton::clicked, this, &LbsCellocation::sltStartParseObtain);
  
}

BaseLocation LbsCellocation::GetCellByLBS(const QString& mncacci)
{
    int pos1 = mncacci.indexOf(",");
    int pos2 = mncacci.lastIndexOf(",");
    if (pos1 < 0 || pos2 < 0 || pos1==pos2)
    {
        return BaseLocation();
    }

    static int httpcode = 0;
    if (httpcode == 429)
    {
        BaseLocation loc;
        loc.errcode = 429;
        return loc;
    }

    BaseLocation baseloc;
    baseloc.mcc = "460";
    baseloc.mnc = mncacci.mid(1, pos1 - 1);
    baseloc.ac = mncacci.mid(pos1+1, pos2-pos1- 1);
    baseloc.ci = mncacci.mid(pos2+1, mncacci.length()-pos2-2);
    baseloc.coord = "bd09";
    QString url = QString("http://api.cellocation.com:84/cell/?mcc=460&mnc=%1&lac=%2&ci=%3&coord=bd09&output=json")
                  .arg(baseloc.mnc).arg(baseloc.ac).arg(baseloc.ci);
    auto response = JQNet::HTTP::get2(url);
    QJsonDocument doc = QJsonDocument::fromJson(response.value("receiveBuffer").toByteArray());
    qDebug() << "GetCellByLBS" << doc;
    if (response.value("httpCode").toInt() == 429)
    {
        httpcode = 429;
        BaseLocation loc;
        loc.errcode = 429;
        return loc;
    }
    if (doc.isObject())
    {
        QJsonObject obj = doc.object();
        baseloc.errcode = obj.value("errcode").toInt();
        if (baseloc.errcode == 0)
        {
            baseloc.lat = obj.value("lat").toString();
            baseloc.lon = obj.value("lon").toString();
            baseloc.radius = obj.value("radius").toString();
            baseloc.address = obj.value("address").toString();
            baseloc.ExtractCityFromAddress();
            return baseloc;
        }
    }

    return BaseLocation();
}





//此网站会屏蔽请求IP
//BaseLocation LbsCellocation::GetCellByJuhe(const QString& mncacci)
//{
//    int pos1 = mncacci.indexOf(",");
//    int pos2 = mncacci.lastIndexOf(",");
//    if (pos1 < 0 || pos2 < 0 || pos1 == pos2)
//    {
//        return BaseLocation();
//    }
//    BaseLocation baseloc;
//    baseloc.mnc = mncacci.mid(1, pos1 - 1);
//    baseloc.ac = mncacci.mid(pos1 + 1, pos2 - pos1 - 1);
//    baseloc.ci = mncacci.mid(pos2 + 1, mncacci.length() - pos2 - 2);
//    QString url = QString("http://v.juhe.cn/cell/Triangulation/query.php");
//    QString body = QString("mcc=460&mnc=%1&lac=%2&ci=%3&hex=10").arg(baseloc.mnc).arg(baseloc.ac).arg(baseloc.ci);
//    QNetworkRequest request;
//    request.setUrl(url);
//    request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0");
//    request.setRawHeader("Accept", "*/*");
//    request.setRawHeader("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
//    //request.setRawHeader("Accept-Encoding", "gzip, deflate");
//    request.setRawHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
//    request.setRawHeader("X-Requested-With", "XMLHttpRequest");
//    request.setRawHeader("X-Requested-With", "XMLHttpRequest");
//    request.setRawHeader("Referer", "http://v.juhe.cn/cell/Triangulation/index.html");
//    request.setRawHeader("Connection", "keep-alive");
//    request.setRawHeader("Origin", "http://v.juhe.cn");
//    request.setRawHeader("Content-Length", QString::number(body.length()).toUtf8());
//    auto response = JQNet::HTTP::post(request, body.toUtf8());
//    QByteArray baResp = response.second;
//    QJsonDocument doc = QJsonDocument::fromJson(baResp);
//    qDebug() <<"GetCellByJuhe"<< doc;
//    if (doc.isObject())
//    {
//        QJsonObject obj = doc.object();
//        if (obj.value("error_code").toInt() == 0)
//        {
//            obj = obj.value("result").toObject();
//            baseloc.lat = obj.value("lat").toString();
//            baseloc.lon = obj.value("lon").toString();
//            baseloc.radius = obj.value("radius").toString();
//            baseloc.address = obj.value("address").toString();
//            return baseloc;
//        }
//    }
//
//    return BaseLocation();
//}

void LbsCellocation::sltSelectFile()
{
    QString filepath = QFileDialog::getOpenFileName(this, "选择文件", "", "Excel文件(*.xlsx);;CSV文件(*.csv);;ALL(*.*)");
    ui.lineEdit->setText(filepath);

}

void LbsCellocation::sltStartParseObtain()
{
    ui.pushButton_2->setEnabled(false);
    QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
    do 
    {
        QString filepath = ui.lineEdit->text();
        QFileInfo fileinfo(filepath);
        if (filepath.isEmpty() || !fileinfo.exists())
        {
            ui.textBrowser->append("请确认文件是否存在！！");
            break;
        }

        QList<QStringList> lstRow = GetAllDataFromFile(filepath);
        if (lstRow.count() <= 1)
        {
            ui.textBrowser->append("未找到所需的基站信息！！");
            break;
        }
        QStringList lstLbs = GetAllLbsOrdered(lstRow);
        ui.textBrowser->append("总计找到" + QString::number(lstLbs.count()) + "条基站信息");
        if (lstLbs.count() < 1)
        {
            break;
        }

        QtCSV::StringData strData;
        strData.addRow(QStringList() << "所属省份" << "所属城市" << "所属区划" << "所属街道" 
                        << "基站类型" << "lac" << "基站代码" 
                        << "基站名称" << "经度" << "纬度");
        for (auto itL = lstLbs.rbegin(); itL !=lstLbs.rend(); ++itL)
        {
            QString lbs = (*itL).mid(10);
            BaseLocation baloc = GetCellByLBS(lbs);
            if (baloc.errcode == 429)
            {
                ui.textBrowser->append("已超过当日最大请求限制，请明日重试！！");
                break;
            }
            if (!baloc.address.isEmpty())
            {
                strData.addRow(QStringList() << baloc.province << baloc.city << baloc.district << baloc.town 
                    << baloc.mnc << baloc.ac << baloc.ci
                    << baloc.address << baloc.lon << baloc.lat);
            }

            ui.textBrowser->append(lbs + "-->" + baloc.address);
            QEventLoop loop;
            QTimer::singleShot(1500, &loop, &QEventLoop::quit);
            loop.exec();
        }
        if (strData.rowCount() <= 1)
        {
            ui.textBrowser->append("未找到任何基站位置信息！！");
            break;
        }

        QString saveFile = "基站归属地" + QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss")+".csv";
        QString savePath = fileinfo.absolutePath() +"/"+ saveFile;
        QtCSV::Writer::write(savePath, strData, ",", "\"", QtCSV::Writer::APPEND, QStringList(), QStringList(), QTextCodec::codecForName("GB18030"));
        ui.textBrowser->append("基站位置信息解析完成，已存入文件" + savePath);

    } while (false);
    ui.pushButton_2->setEnabled(true);
}

QList<QStringList> LbsCellocation::GetAllDataFromFile(QString filepath)
{
    QList<QStringList> lstRow;
    if (filepath.endsWith("xlsx"))
    {
        QXlsx::Document xlsx(filepath);
        if (!xlsx.isLoadPackage())
        {
            qDebug() << "[ReadExcel.xlsx] failed to load package";
            return lstRow;
        }
        int indexLbs = 0;
        int indexTimes = 0;
        int countCol = 0;
        for (int i = 1; i < 20; ++i)
        {
            auto cell = xlsx.cellAt(1, i);
            if (cell == nullptr)
            {
                continue;
            }
            QString var = cell->readValue().toString();
            if (var == "定位地点")
            {
                indexLbs = i - 1;
            }
            else if (var == "通联次数")
            {
                indexTimes = i - 1;
            }

            if (!var.isEmpty())
            {
                ++countCol;
            }
        }
        if (indexLbs <= 0 || indexTimes <= 0)
        {
            qDebug() << "[ReadExcel.xlsx] not find 定位地点or通联次数";
            return lstRow;
        }

        for (int row = 1; row < 10000; ++row)
        {
            QStringList line;
            for (int col = 1; col <= countCol; ++col)
            {
                auto cell = xlsx.cellAt(row, col);
                if (cell == nullptr)
                {
                    continue;
                }
                QString var = cell->readValue().toString();
                line.append(var);
            }
            if (line.size() < countCol)
            {
                break;
            }
            lstRow.append(line);
        }
    }
    else
    {
        lstRow = QtCSV::Reader::readToList(filepath, ",", "\"", QTextCodec::codecForName("GB18030"));
    }

    return lstRow;
}

QStringList LbsCellocation::GetAllLbsOrdered(const QList<QStringList>& lstRow)
{
    int indexLbs = 1;
    int indexTimes = 5;
    auto header = lstRow.constFirst();
    for (int i = 0; i < header.size(); i++)
    {
        if (header.at(i) == "定位地点")
        {
            indexLbs = i;
        }
        else if (header.at(i) == "通联次数")
        {
            indexTimes = i;
        }
    }
    QMap<QString, int> mapLbs;
    for each (const auto & row in lstRow)
    {
        QString cell = row.at(indexLbs);
        int times = row.at(indexTimes).toInt();
        if (cell.contains(QRegularExpression(R"(\(\d+,\d+,\d+\))")))
        {
            mapLbs[cell] += times;
        }
    }

    QStringList lstLbs;
    auto it = mapLbs.constBegin();
    for (; it != mapLbs.constEnd(); ++it)
    {
        QString strTimes = QString("%1").arg(it.value(), 8, 10, QChar('0'));
        strTimes.append("##");
        strTimes.append(it.key());
        lstLbs.append(strTimes);
    }
    lstLbs.sort();

    return lstLbs;
}

void BaseLocation::ExtractCityFromAddress()
{
    int offset = 0;
    {
        QRegularExpression re(R"((?<province>[^省]+自治区|.*?省|.*?特别行政区|.*?市))");
        QRegularExpressionMatch match = re.match(address, 0);
        if (match.hasMatch())
        {
            QString matchedText = match.captured(0); // 整个匹配的文本
            province = matchedText;
            offset += matchedText.length();
        }
    }

    if (province.endsWith("市"))
    {
        if ((province == "北京市") || (province == "上海市") || (province == "天津市") || (province == "重庆市"))
        {
            city = province;
        }
        else
        {
            province = "";
            return;
        }
    }
    else
    {
        QRegularExpression re(R"((?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县))");
        QRegularExpressionMatch match = re.match(address, offset);
        if (match.hasMatch())
        {
            QString matchedText = match.captured(0); // 整个匹配的文本
            city = matchedText;
            offset += matchedText.length();
        }
    }

    {
        QRegularExpression re(R"((?<district>[^县]+县|.+区|.+市|.+旗|.+海域|.+岛))");
        QRegularExpressionMatch match = re.match(address, offset);
        if (match.hasMatch())
        {
            QString matchedText = match.captured(0); // 整个匹配的文本
            district = matchedText;
            offset += matchedText.length();
        }
    }

    {
        QRegularExpression re(R"((?<town>[^区]+区|.+镇|.+乡|.+街道))");
        QRegularExpressionMatch match = re.match(address, offset);
        if (match.hasMatch())
        {
            QString matchedText = match.captured(0); // 整个匹配的文本
            town = matchedText;
            offset += matchedText.length();
        }
    }
}
